
package com.sun.showcase.biz.mall.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sun.showcase.biz.basic.service.BasicFeignService;
import com.sun.showcase.biz.mall.dao.OrderDao;
import com.sun.showcase.biz.mall.service.*;
import com.sun.showcase.client.domain.mall.*;
import com.sun.showcase.client.query.mall.OrderGoodsQuery;
import com.sun.showcase.client.query.mall.OrderQuery;
import com.sun.showcase.client.query.mall.ShopBillQuery;
import com.sun.showcase.client.vo.order.SaveOrderEntity;
import com.sun.showcase.client.vo.order.SaveOrderGoodsEntity;
import com.sun.showcase.client.vo.order.SaveOrderResultEntity;
import com.sun.showcase.client.vo.order.SaveSkuEntity;
import com.sun.showcase.exception.DefaultException;
import com.sun.showcase.pojo.DataGrid;
import com.sun.showcase.pojo.Pager;
import com.sun.showcase.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service("orderService")
@Transactional
public class OrderServiceImpl implements OrderService{
	@Autowired
	private OrderDao orderDao;
	@Autowired
	private SkuService skuService;
	@Autowired
	private GoodsService goodsService;
	@Autowired
	private AddressService addressService;
	@Autowired
	private OrderGoodsService orderGoodsService;
	@Autowired
	private BasicFeignService basicFeignService;
	@Autowired
	private ShoppingCartService shoppingCartService;
	@Autowired
	private FreightDetailService freightDetailService;
	@Autowired
	private PlatformConfigService platformConfigService;
	@Autowired
	private ShopService shopService;
	@Autowired
	private ShopBillService shopBillService;
	
	public void setOrderDao(OrderDao dao) {
		this.orderDao = dao;
	}

	public DataGrid datagrid(OrderQuery orderQuery) {
		DataGrid j = new DataGrid();
		Pager<Order> pager  = find(orderQuery);
		j.setRows(getQuerysFromEntitys(pager.getRecords()));
		j.setTotal(pager.getTotalRecords());
		return j;
	}

	private List<OrderQuery> getQuerysFromEntitys(List<Order> orders) {
		List<OrderQuery> orderQuerys = new ArrayList<OrderQuery>();
		if (orders != null && orders.size() > 0) {
			for (Order tb : orders) {
				OrderQuery b = new OrderQuery();
				BeanUtils.copyProperties(tb, b);
				orderQuerys.add(b);
			}
		}
		return orderQuerys;
	}

	private Pager<Order> find(OrderQuery orderQuery) {
		Page<Order> page = PageHelper.startPage(orderQuery.getPage().intValue(), orderQuery.getRows().intValue());
		List<Order> list = orderDao.findList(orderQuery);
		Pager<Order> pager = new Pager<Order>();
		pager.setRecords(list);
		pager.setTotalRecords(page.getTotal());
		return  pager;
		
	}
	


	public Order add(OrderQuery orderQuery) {
		Order t = new Order();
		BeanUtils.copyProperties(orderQuery, t);
		t.setActiveFlag("1");
		t.setCreateDate(new Date());
	    t.setId(UuidUtil.get32UUID());
	    t.setOrderCreateDate(new Date());
	    t.setIfEvaluate(StringConstant.ZERO);
	    t.setSendStatus(StringConstant.ZERO);
	    t.setSettleStatus(StringConstant.ZERO);
		orderDao.save(t);
		orderQuery.setId(t.getId());
		return t;
		
	}

	public void update(OrderQuery orderQuery) {
		Order t = orderDao.getById(orderQuery.getId());
	    if(t != null) {
	    	BeanUtils.copyProperties(orderQuery, t);
		    t.setModifiedBy(LoginContextHolder.get().getUserId());
		    t.setModifiedByName(LoginContextHolder.get().getUserName());
		    t.setModifiedDate(new Date());
	    	orderDao.update(t);
		}
	}
	
	/**
	 * 根据条件更新部分字段   新建一个query封装需要更新的字段
	 * searchMap封装更新条件
	 * */
	public void updatePart(OrderQuery orderQuery) {
	    orderDao.updatePart(orderQuery);
	}

	public void delete(String[] ids) {
		orderDao.deleteAc(ids);
	}

	//逻辑删除 更新状态位
	public void deletePt(String[] ids) {
		orderDao.deletePt(ids);
	}

	public Order get(OrderQuery orderQuery) {
		return orderDao.getById(orderQuery.getId());
	}

	public Order get(String id) {
		return orderDao.getById(id);
	}

	
	public List<OrderQuery> listAll(OrderQuery orderQuery) {
	    List<Order> list = orderDao.findList(orderQuery);
		List<OrderQuery> listQuery =getQuerysFromEntitys(list) ;
		return listQuery;
	}
	private synchronized String getNextCode() {
		return basicFeignService.getNextCodeById(1L);
	}
	@Override
	public ExecuteResult<SaveOrderResultEntity> saveOrder(SaveOrderEntity info) {
		ValidatorUtils.validate(info);
		ExecuteResult<SaveOrderResultEntity> res = new ExecuteResult<SaveOrderResultEntity>();
		SaveOrderResultEntity entity = new SaveOrderResultEntity();
		Double allTotalAmount = 0D;
		Address ads = addressService.get(info.getAddressId());
		if(ads == null) {
			res.addErrorMessage("无效收货地址");
			return res;
		}
		List<String> orderIds = new ArrayList<String>();
		OrderQuery order = new OrderQuery();
		OrderGoodsQuery orderGoods = new OrderGoodsQuery();
		Map<String,Sku> skuMap = null;
		Map<String,Shop> shopCache = new HashMap<String,Shop>();
		for(SaveOrderGoodsEntity og : info.getGoodsList()) {
			Double totalAmount = 0D;
			Double feightAmount = 0D;
			if(shopCache.containsKey(og.getShopId())) {
				order.setShopOwnerId(shopCache.get(og.getShopId()).getUserId());
				order.setShopOwnerName(shopCache.get(og.getShopId()).getUserName());
			}else {
				Shop sp = shopService.get(og.getShopId());
				if(sp == null) {
					res.addErrorMessage("无效店铺");
					return res;
				}
				shopCache.put(og.getShopId(), sp);
				order.setShopOwnerId(sp.getUserId());
				order.setShopOwnerName(sp.getUserName());
			}
			order.setShopId(og.getShopId());
			order.setShopName(og.getShopName());
			order.setUserId(info.getUserId());
			order.setUserName(info.getUserName());
			order.setPayType(info.getPayType());
			order.setLinkAddress(ads.getReceiptorAreaName()+" "+ads.getReceiptorAddres());
			order.setLinkPerson(ads.getReceiptorName());
			order.setLinkPhone(ads.getReceiptorPhone());
			order.setOrderStateCode("1");
			order.setOrderStateName("待付款");
			order.setOrderNo(this.getNextCode());
			skuMap = new HashMap<String,Sku>();
			for(SaveSkuEntity ss : og.getSkuList()) {
				Sku sku = skuService.get(ss.getSkuId());
				if(sku == null) {
					throw new DefaultException("无效商品");
				}
				Goods g = goodsService.get(sku.getGoodsId());
				if(g == null) {
					throw new DefaultException("无效商品");
				}
				if(sku.getCount()< ss.getBuyNum()) {
					//FIXME 并发问题
					throw new DefaultException(sku.getName()+" 库存不足");
				}
				skuMap.put(sku.getId(), sku);
				Double cu = ArithUtil.mul(sku.getSellPrice(), ss.getBuyNum());
				totalAmount = ArithUtil.add(totalAmount, cu);
				if(StringUtils.isNoneEmpty(g.getFreightId())) {
					FreightDetail f = freightDetailService.getFreight(g.getFreightId(), cu);
					if(f != null && f.getFreightExpense() != null) {
						feightAmount = ArithUtil.add(feightAmount, f.getFreightExpense());
					}
				}
				
			}
			if(totalAmount == 0) {
				order.setOrderStateCode("2");
				order.setOrderStateName("已付款");
			}
			order.setTotalPayAmount(ArithUtil.add(feightAmount, totalAmount));
			order.setSumAmount(totalAmount);
			order.setFreightAmount(feightAmount);
			order.setSettleAmount(order.getTotalPayAmount());
			Order curOrder = this.add(order);
			for(SaveSkuEntity ss : og.getSkuList()) {
				Sku sku = skuMap.get(ss.getSkuId());
				orderGoods.setOrderId(curOrder.getId());
				orderGoods.setBuyNum(ss.getBuyNum());
				orderGoods.setGoodsId(sku.getGoodsId());
				orderGoods.setGoodsName(sku.getGoodsName());
				orderGoods.setSkuId(sku.getId());
				orderGoods.setSkuName(sku.getName());
				orderGoods.setUserId(info.getUserId());
				orderGoods.setUserName(info.getUserName());
				orderGoods.setSalePrice(sku.getSellPrice());
				orderGoods.setDealPrice(sku.getSellPrice());
				orderGoods.setCalUnit(sku.getFormat());
				orderGoods.setSpecifications(sku.getName());
				orderGoods.setMainPictureAddress(ss.getPic());
				orderGoodsService.add(orderGoods);
				skuService.updateStockNum(sku.getId(), ss.getBuyNum());
				goodsService.updateSellCount(sku.getGoodsId(), ss.getBuyNum());
				if(StringUtils.isNotEmpty(ss.getCartId())) {
					shoppingCartService.deleteById(ss.getCartId());
				}
			}
			allTotalAmount = allTotalAmount + totalAmount;
			orderIds.add(curOrder.getId());
		}
		shopCache = null;
		entity.setMoney(allTotalAmount);
		entity.setOrderIds(orderIds);;
		res.setResult(entity);
		res.setSuccessMessage("下单成功！");
		return res;
	}

	@Override
	public DataGrid datagrid4App(OrderQuery orderQuery) {
		DataGrid j = new DataGrid();
		Pager<Order> pager  = find(orderQuery);
		List<OrderQuery> orderQuerys = new ArrayList<OrderQuery>();
		if (pager.getRecords() != null && pager.getRecords().size() > 0) {
			OrderGoodsQuery q = new OrderGoodsQuery();
			for (Order tb : pager.getRecords()) {
				OrderQuery b = new OrderQuery();
				q.setOrderId(tb.getId());
				List<OrderGoodsQuery> list = orderGoodsService.listAll(q);
				BeanUtils.copyProperties(tb, b);
				b.setGoodsList(list);
				orderQuerys.add(b);
			}
		}
		j.setRows(orderQuerys);
		j.setTotal(pager.getTotalRecords());
		return j;
	}

	@Override
	public void cancelOrder(String id) {
		orderDao.cancelOrder(id);
	}

	@Override
	public Long reciveOrder(String id) {
		return orderDao.reciveOrder(id);
	}

	@Override
	public Long paySuccessOrder(String id,String payType,String payOrderNo) {
		return orderDao.paySuccessOrder(id,payType,payOrderNo);
	}

	@Override
	public void sendOrder(OrderQuery orderQuery) {
		OrderQuery update = new OrderQuery();
		update.getSearchMap().put(StringConstant.ID, orderQuery.getId());
		update.getSearchMap().put("order_state_code", StringConstant.TWO);
		update.setExpressCompanyCode(orderQuery.getExpressCompanyCode());
		update.setExpressCompanyName(orderQuery.getExpressCompanyName());
		update.setExpressOrderCode(orderQuery.getExpressOrderCode());
		update.setSendStatus(StringConstant.ONE);
		update.setOrderSendDate(new Date());
		this.updatePart(update);
	}

	@Override
	public void comment(String id) {
		orderDao.comment(id);
	}

	@Override
	public void autoCompeleteOrder() {
		PlatformConfig conf = platformConfigService.get();
		//查询所有order_state_code=2 已发货订单 SendStatus=1
		OrderQuery query = new OrderQuery();
		query.setActiveFlag("1");
		query.setSendStatus(StringConstant.ONE);
		query.setOrderStateCode(StringConstant.TWO);
		query.setMaxCompeleteDay(conf.getOrderCompleteDay());
		this.dealUnreciveOrder(1, query);
	}
	
	private void dealUnreciveOrder(int startPage,OrderQuery query) {
		Page<Order> page = PageHelper.startPage(startPage, 100);
		List<Order> list = orderDao.findList(query);
		for(Order o : list) {
			//更新为确认收货
			this.reciveOrder(o.getId());
		}
		if(startPage < page.getPageNum()) {
			//查询处理下一页
			startPage++;
			this.dealUnreciveOrder(startPage, query);
		}
	}

	@Override
	public void settleOrder() {
		PlatformConfig conf = platformConfigService.get();
		//查询所有order_state_code=2 已发货订单 SettleStatus=0
		OrderQuery query = new OrderQuery();
		query.setActiveFlag("1");
		query.setSettleStatus(StringConstant.ZERO);
		query.setOrderStateCode(StringConstant.THREE);
		query.setMaxSettleDay(conf.getShopSettleDay());
		this.dealUnsettleOrder(1, query);
	}
	
	private void dealUnsettleOrder(int startPage,OrderQuery query) {
		Page<Order> page = PageHelper.startPage(startPage, 100);
		List<Order> list = orderDao.findList(query);
		for(Order o : list) {
			//更新已结算状态
			OrderQuery up = new OrderQuery();
			up.getSearchMap().put(StringConstant.ID, o.getId());
			up.setSettleStatus(StringConstant.ONE);
			this.updatePart(up);
			if(o.getSettleAmount()<=0) {
				continue;
			}
			//更新店主余额, FIXME 现在没有优惠券，不需要扣除任何金额
			basicFeignService.updateBalance(o.getShopOwnerId(), o.getSettleAmount());
			//增加账单
			ShopBillQuery ad = new ShopBillQuery();
    		ad.setBussinessId(o.getOrderNo());
    		ad.setAmount(o.getSettleAmount());
    		ad.setType(StringConstant.ZERO);
    		ad.setStatus(StringConstant.ONE);
    		ad.setUserId(o.getShopOwnerId());
    		ad.setUserName(o.getShopOwnerName());
    		ad.setRemark("订单结算");
    		shopBillService.add(ad);
		}
		if(startPage < page.getPageNum()) {
			//查询处理下一页
			startPage++;
			this.dealUnsettleOrder(startPage, query);
		}
	}

	@Override
	public void updateSettleStatus(String id, String status) {
		OrderQuery up = new OrderQuery();
		up.getSearchMap().put(StringConstant.ID, id);
		up.setSettleStatus(status);
		this.updatePart(up);
	}

	@Override
	public Long updateSettleAmount(String id, Double settleAmount) {
		return this.orderDao.updateSettleAmount(id, settleAmount);
	}

	@Override
	public Map<String, Object> homeChartData() {
		Map<String, Object> map = new HashMap<String,Object>();
		map.put("todayOrderCount", 0);
		map.put("todayOrderAmount", 0);
		map.put("yesterdayOrderAmount", 0);
		map.put("unpayOrderCount", 0);
		map.put("unsendOrderCount", 0);
		map.put("unreceiveOrderCount", 0);
		if(StringUtils.isEmpty(LoginContextHolder.get().getShopId())) {
			return map;
		}
		OrderQuery q = new OrderQuery();
		q.setShopId(LoginContextHolder.get().getShopId());
		
		Date today = new Date();
		Date yesteroday = DateUtils.dateAddSub(today, -1);
		q.setOrderCreateDate(today);
		Long todayOrderCount = this.orderCount(q);
		Double todayOrderAmount = this.orderSum(q);
		q.setOrderCreateDate(yesteroday);
		Double yesterdayOrderAmount = this.orderSum(q);
		q.setOrderCreateDate(null);
		q.setOrderStateCode("1");
		Long unpayOrderCount = this.orderCount(q);
		q.setOrderStateCode("2");
		q.setSendStatus("0");
		Long unsendOrderCount = this.orderCount(q);
		q.setSendStatus("1");
		Long unreceiveOrderCount = this.orderCount(q);
		map.put("todayOrderCount", todayOrderCount);
		map.put("todayOrderAmount", todayOrderAmount);
		map.put("yesterdayOrderAmount", yesterdayOrderAmount);
		map.put("unpayOrderCount", unpayOrderCount);
		map.put("unsendOrderCount", unsendOrderCount);
		map.put("unreceiveOrderCount", unreceiveOrderCount);
		
		return map;
	}

	@Override
	public Long orderCount(OrderQuery orderQuery) {
		return this.orderDao.orderCount(orderQuery);
	}

	@Override
	public Double orderSum(OrderQuery orderQuery) {
		return orderDao.orderSum(orderQuery);
	}

	@Override
	public List<Map<String, Object>> orderChartData(OrderQuery orderQuery) {
		return orderDao.orderChartData(orderQuery);
	}
	
	
}
